# apps/questions/tests.py
from django.urls import reverse
from rest_framework.test import APITestCase
from rest_framework import status
from django.contrib.auth import get_user_model
from apps.questions.models import Question, QuestionTag
from apps.subjects.models import Subject
from apps.tags.models import Tag
from apps.users.models import QBUser

User = get_user_model()


class QuestionTestCase(APITestCase):
    def setUp(self):
        Question.objects.all().delete()
        # 创建教师用户
        self.teacher1 = User.objects.create_user(
            username='teacher1',
            password='pass123',
            role='teacher',
            email='teacher1@example.com'  # 添加唯一 email
        )
        self.teacher2 = User.objects.create_user(
            username='teacher2',
            password='pass123',
            role='teacher',
            email='teacher2@example.com'  # 添加唯一 email
        )
        # 管理员
        self.admin = User.objects.create_superuser(
            username='admin',
            password='admin123',
            role='admin',
            email='admin@example.com'     # 超级用户通常需要 email
        )


        # 创建学科和标签
        self.subject = Subject.objects.create(name="数学")
        self.tag1 = Tag.objects.create(name="代数")
        self.tag2 = Tag.objects.create(name="方程")

        # 登录 teacher1
        self.client.login(username='teacher1', password='pass123')
        self.client.force_authenticate(user=self.teacher1)

        # 正确的试题数据
        self.question_data = {
            "title": "What is 2 + 2?",
            "question_type": "single",
            "difficulty": 3,
            "analysis": "Basic arithmetic",
            "reference": "教材P10",
            "subject_id": self.subject.id,
            "tag_ids": [self.tag1.id, self.tag2.id],
            "status": "draft"
        }

        self.url_list = reverse('question-list')
        self.detail_url = None  # 等创建后再赋值

    def test_create_question_with_tags(self):
        """测试创建试题并关联标签"""
        response = self.client.post(self.url_list, self.question_data, format='json')

        self.assertEqual(response.status_code, status.HTTP_201_CREATED)
        self.assertEqual(response.data['title'], self.question_data['title'])
        self.assertEqual(response.data['subject']['id'], self.subject.id)
        self.assertEqual(response.data['subject']['name'], self.subject.name)
        self.assertEqual(response.data['creator']['username'], 'teacher1')
        self.assertEqual(len(response.data['tags']), 2)
        self.assertIn('代数', [tag['name'] for tag in response.data['tags']])

        # 验证数据库
        question = Question.objects.get(id=response.data['id'])
        self.assertEqual(question.creator, self.teacher1)
        self.assertEqual(QuestionTag.objects.filter(question=question).count(), 2)

        # 保存用于后续测试
        self.detail_url = reverse('question-detail', args=[question.id])

    def test_user_can_only_see_own_questions(self):
        """测试用户只能看到自己的试题"""
        # teacher1 创建一个题
        self.client.post(self.url_list, self.question_data, format='json')

        # teacher2 登录
        self.client.logout()
        self.client.login(username='teacher2', password='pass123')
        self.client.force_authenticate(user=self.teacher2)

        response = self.client.get(self.url_list)
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(len(response.data), 0)  # 看不到 teacher1 的题

        # teacher2 创建自己的题
        self.client.post(self.url_list, {**self.question_data, "title": "Teacher2's Question"}, format='json')
        response = self.client.get(self.url_list)
        self.assertEqual(len(response.data), 1)
        self.assertEqual(response.data[0]['title'], "Teacher2's Question")

    def test_admin_can_see_all_questions(self):
        """测试管理员可以看到所有试题"""
        # teacher1 创建一个题
        self.client.post(self.url_list, self.question_data, format='json')

        # admin 登录
        self.client.logout()
        self.client.login(username='admin', password='admin123')
        self.client.force_authenticate(user=self.admin)

        response = self.client.get(self.url_list)
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertGreaterEqual(len(response.data), 1)  # 至少能看到 teacher1 的题

    def test_update_question_tags(self):
        """测试更新试题并修改标签"""
        # 创建试题
        response = self.client.post(self.url_list, self.question_data, format='json')
        question_id = response.data['id']
        url = reverse('question-detail', args=[question_id])

        # 更新：只保留一个标签
        updated_data = {
            "title": "Updated Question",
            "difficulty": 5,
            "tag_ids": [self.tag1.id],  # 只保留“代数”
            "subject_id": self.subject.id
        }

        response = self.client.put(url, updated_data, format='json')
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(len(response.data['tags']), 1)
        self.assertEqual(response.data['tags'][0]['name'], '代数')

        # 验证数据库
        question = Question.objects.get(id=question_id)
        self.assertEqual(QuestionTag.objects.filter(question=question).count(), 1)
        self.assertEqual(question.title, "Updated Question")

    def test_increment_view_count(self):
        """测试增加浏览量"""
        # 创建试题
        response = self.client.post(self.url_list, self.question_data, format='json')
        question_id = response.data['id']
        url = reverse('question-increment_view', args=[question_id])

        # 第一次增加
        response = self.client.post(url)
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(response.data['view_count'], 1)

        # 第二次
        response = self.client.post(url)
        self.assertEqual(response.data['view_count'], 2)

        # 验证数据库
        question = Question.objects.get(id=question_id)
        self.assertEqual(question.view_count, 2)

    def test_bulk_delete_owned_questions(self):
        """测试批量删除（仅限自己创建的）"""
        # 创建两个自己的题
        q1 = Question.objects.create(
            title="Q1", question_type="single", difficulty=3,
            subject=self.subject, creator=self.teacher1
        )
        q2 = Question.objects.create(
            title="Q2", question_type="multiple", difficulty=4,
            subject=self.subject, creator=self.teacher1
        )
        # 创建一个别人的题（不应被删除）
        q3 = Question.objects.create(
            title="Q3", question_type="single", difficulty=2,
            subject=self.subject, creator=self.teacher2
        )

        url = reverse('question-bulk-delete')
        data = {"ids": [q1.id, q2.id, q3.id]}  # 包含别人的题

        # 以 teacher1 身份请求
        self.client.force_authenticate(user=self.teacher1)
        response = self.client.post(url, data, format='json')

        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(response.data['deleted'], 2)  # 只能删自己的

        # 验证
        self.assertFalse(Question.objects.filter(id=q1.id).exists())
        self.assertFalse(Question.objects.filter(id=q2.id).exists())
        self.assertTrue(Question.objects.filter(id=q3.id).exists())  # 依然存在

    def test_bulk_delete_admin_can_delete_all(self):
        """测试管理员可以批量删除所有试题"""
        q1 = Question.objects.create(
            title="Q1", creator=self.teacher1, subject=self.subject,
            question_type="single", difficulty=3
        )
        q2 = Question.objects.create(
            title="Q2", creator=self.teacher2, subject=self.subject,
            question_type="multiple", difficulty=4
        )

        url = reverse('question-bulk-delete')
        data = {"ids": [q1.id, q2.id]}

        self.client.force_authenticate(user=self.admin)
        response = self.client.post(url, data, format='json')

        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(response.data['deleted'], 2)

        self.assertFalse(Question.objects.filter(id=q1.id).exists())
        self.assertFalse(Question.objects.filter(id=q2.id).exists())

    def test_filter_and_search_questions(self):
        """测试过滤和搜索"""
        # 创建两个题
        Question.objects.create(
            title="关于代数的题目",
            question_type="single",
            difficulty=3,
            subject=self.subject,
            creator=self.teacher1,
            status="published"
        )
        Question.objects.create(
            title="关于几何的题目",
            question_type="multiple",
            difficulty=5,
            subject=self.subject,
            creator=self.teacher1,
            status="draft"
        )

        # 测试搜索
        response = self.client.get(self.url_list, {'search': '代数'})
        self.assertEqual(len(response.data), 1)
        self.assertIn('代数', response.data[0]['title'])

        # 测试过滤
        response = self.client.get(self.url_list, {'difficulty': 5})
        self.assertEqual(len(response.data), 1)
        self.assertEqual(response.data[0]['difficulty'], 5)

        response = self.client.get(self.url_list, {'status': 'draft'})
        self.assertEqual(len(response.data), 1)
        self.assertEqual(response.data[0]['status'], 'draft')

    def test_permission_denied_for_unauthenticated_user(self):
        """测试未登录用户无法访问"""
        self.client.logout()
        response = self.client.post(self.url_list, self.question_data, format='json')
        self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)